II Something
by Clark Hugh Stiles
November 28, 2001 

Interface -- In modern programming environments, interface is everything. Design for the user, and the rest is supposed to follow. Apple popularized this approach, and spent a lot of time making things easier on programmers to provide such an interface. Compare that with Wintel programs, where highlighting text to copy reveals that the computer, OS, and that other company knows better than you what you're trying to highlight. Hating that problem (and the none too smart quotes) leads me to use NotePad a lot when I'm at the library or at work, unless I need to search and replace based on invisible characters or wild cards. 

This first routine will do nothing but get the user's input from the keyboard: 

Program Listing 1: 
CALL -151
!
1000:JSR FDOC
LDA C000
RTS

[control-C] 
End of Program Listing. 

The ROM (Read-Only Memory) routine at $FD0C (64780 in decimal) doesn't do anything but wait for a keypress (other than the modification keys such as the shift keys and open- or closed-apple). The value is left at $C000. There's no need to handle anything else. Ordinarily when one PEEKs the keyboard, one must then POKE any old value into the keyboard strobe location. To show that this alternative works, try the same thing in BASIC (the method seen in the Disk.Menu program): 

Program Listing 2: 
1 CALL 64780:K=PEEK(49152) 
End of Program Listing. 

That's an input anything routine in BASIC, the shortest one I know. The value of the key pressed is left in the numeric variable K. In the case of the first listing, the value is left in the Accumulator. It's simple enough to CMP (Compare) the value with various acceptable alternatives in the first listing, and use the value K to figure out what to do in the second example (Disk.Menu uses ON K goto to evaluate every keystroke). Since the arrow keys are control- characters (i.e., values less than 32, since the $FD0C ROM routine also pulls off the high bit) building a simple interface should be, well, simple. 

The interface will allow the user to toggle through the valid unit numbers using the arrow keys. This will make the finished program point 'n' shoot, and not insist that the user type in a slot and drive number which may be incorrect (and it would take more code to do it that way). Since we've got access to a routine that processes and stores those values, that will be the first interface subroutine. It might be nice to know what number to expect for each arrow key: 

Program Listing 3: 
1 CALL 64780:K=PEEK(49152):PRINT K:IF K<>27 THEN GOTO 1 
End of Program Listing. 

This uses the input anything technique from immortal AppleSoft BASIC to print out the ASCII value of the keypresses. If Escape is pressed, the program ends. 

Program Listing 4: 
CALL -151
!
1000:JSR FDOC
LDA C000
CMP #$0B
BEQ 100E
CMP #$0A
BNE 1000
RTS

[control-C] 
End of Program Listing. 

The up arrow is $0B (11 in decimal) and the down is $0A (10 in decimal). If the first CMP reveals that the keystroke is equal to 11, the program Branches to the handler for up arrow. If the second CMP reveals that the keystroke is NOT a down arrow, the program Branches to the check routine. If it is equal to down arrow, the program falls through the BNE (Branch on Not Equal) to find the up arrow handler. Seems easy enough. 

In this example, the BEQ points to the RTS, which is where the up arrow handler will go, and if that fails it falls through to the next comparison, the down arrow. Right now it falls through if found, eventually to the handler. But hey, we're not ready for that yet. 

You must realize by now that there will be a keystroke checker routine for each subroutine, because of context. When the user wants to navigate the field of bytes in the disk block loaded into memory, the arrow keys will move the cursor around, and the acceptable keystrokes (0-9 and A-F) need to be "legal". To jump to the various functions, control- keys will be "hot" all the time. Naturally, the one needed to access a given subroutine can be omitted in that subroutine. 

There will need to be a subroutine for choosing the unit number (a one byte value used to designate valid ProDOS volumes using a drive/slot value that has been combined as four bits), and that needs to accept the arrow keys and some other control- keys. 

There will need to be a subroutine for choosing the block number on the selected disk (default is zero) with values from zero to 65535. That will also be point and shoot, with some sort of skip ahead capability to save time. 

The subroutine for finding the valid volumes is done. 

The subroutine for reading the disk is done. 

The subroutine for writing the disk is all but done. Instead of toggling the value (from READ_ to WRITE_) which could be playing with fire, we'll write a second routine with a "press Y to write to disk" warning. 

There will need to be a subroutine for navigating the bytes that have been read, and that will need to recognize the commands (control- keys) and arrows. The commands will consist of O (for ONLINE), R (for READ_BLOCK), W (for WRITE_BLOCK), and one or more mode commands for the editing functions. The legal hex values are in fact as shown, 0-9 and A-F, but it will sometimes be convenient to enter strings of letters or numbers, or possibly decimal numbers. 

We'll use a previously explored technique to set up one of these: 

Program Listing 5: 
CALL -151
!
1000:LDA 24
STA 1EE3
LDA 25
STA 1EE4
LDA #$09
STA 24
LDA #$01
STA 25
JSR FC22
LDA 1EEA
PHA
LDA 1EE9
PHA
TAX
JSR F941
LDA #$A0
JSR FDED
LDA #$DB
JSR FDED
PLA
TAX
PLA
JSR ED24
LDA #$DD
JSR FDED
LDX #$05
JSR F94A
LDA 1EE3
STA 24
LDA 1EE4
STA 25
JSR FC22
RTS
[return]
1000L
[control-C,return] 
End of Program Listing. 

All this does is save out the current V and HTAB values, set them to the correct values for the subroutine (in this case, the one for changing the block number to be read or written), and print the current value, first in hex, then in decimal (in brackets) and five trailing spaces to eliminate the "ghosts". When we're done with this it will evaluate the keystrokes and allow us to scroll through the values. 

The plan is to use the up and down arrows to scroll th ...[Message truncated] 